查看原文
其他

教程|编写一个 Substrate 模块

PolkaWorld 2020-11-11

自己创建一个 Pallet

在本教程中, 你将编写一个存在于其自身 crate(包装箱)里的 Substrate 模块,并将其包含在基于 substrate-node-template的节点中。

安装 Node Template

当你学习完教程:创建你的第一条Substrate链[1] 之后,你应该已经在计算机上编译了 Substrate Node Template[2]v2.0.0-alpha.8 版本,如果没有的话, 请先学习完教程。

如果你是有经验的开发人员,倾向于选择跳过该教程,建议你可以根据自述文件中的说明安装节点模板。

克隆 Pallet 模板

我们不会将 Pallet(模块)直接写为节点模板的一部分,而是写成一个单独的 Rust crate。这种形式让我们可以和节点分开发布 Pallet,也可以让其他人轻松的将该 Pallet 导入自己的 Substrate Runtime。

在你的节点模板的 pallets 目录中克隆 Substrate pallet template:

cd pallets
git clone -b v2.0.0-alpha.8 https://github.com/substrate-developer-hub/substrate-pallet-template test-pallet

在本教程中,我们将 pallet template (模块模板) 放在 node template (节点模板)的目录结构中。这种形式不是必须的,你可以将 pallet template 放置在任意位置。另一种流行的做法是将其作为 node template 的同级。

Substrate Pallet 模板

让我们从 Cargo.toml 文件开始探索 Substrate Pallet template。

重命名 crate

Cargo.toml 文件中, 你可以更新 crate 的名称和作者身份。在本教程中,我们集中讲如何创建和使用 pallet (模块),而不是编写 pallet (模块)逻辑。我们称之为 test-pallet

Cargo.toml 的开头是这样展示的:

pallets/test-pallet/Cargo.toml

[package]
authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']
description = 'Substrate FRAME pallet template'
edition = '2018'
homepage = 'https://substrate.io'
license = 'Unlicense'
name = 'test-pallet'
repository = 'https://github.com/paritytech/substrate/'
version = '2.0.0-alpha.8'

编译 Template Pallet

如果你已按照本教程的步骤进行操作 ,并将模板模块克隆到节点模板的 pallets 目录中,则需要将模板模块添加到 Cargo.toml 文件的 workspace.members 数组中。在节点模板目录的根目录中;你将需要包括路径和包的名称,所以需要将此元素添加到 members 数组中: 'pallets/test-pallet',

你应该能够使用以下命令成功编译 Substrate pallet template :

cd test-pallet
cargo build --release

模块的 std 功能

在这个 pallets/test-pallet/Cargo.toml 文件中,你会注意到关于 "std 功能" 的几行内容,在 Rust 中, 当你启用 “std 功能”  时,就可以让你的项目访问 Rust标准库[3]。这在构建本机二进制时非常好用。

但是, Substrate 也将 runtime 代码构建到 WebAssembly (Wasm)。在这种情况下, 我们使用 cargo 功能禁用 Rust 标准库。因此,我们用于 Pallet (模块)及整个 runtime 时的所有依赖项都必须能够使用 `no_std`[4] 功能。Cargo.toml 文件会告诉模块的依赖项,仅在该模块还使用 std 功能时才使用其 std 功能, 如下所示:

pallets/test-pallet/Cargo.toml

[features]
default = ['std']
std = [
'codec/std',
'frame-support/std',
'frame-system/std',
]

Substrate 的依赖性需保持一致

所有的 Substrate 模块都是依赖于一些较低级别的 FRAME 库,例如 frame-systemframe-support。这些库是从 crates.io 中提取的。当人们构建自己的基于 FRAME  的 runtime 时, 他们还将依赖于这些低级库. 并且你需要确保 pallet 和 runtime 之间保持一致性依赖关系。

pallets/test-pallet/Cargo.toml

# --snip--

[dependencies.frame-support]
git = 'https://github.com/paritytech/substrate.git'
default-features = false
tag = 'v2.0.0-alpha.8'

从上面的代码片段中,我们看到该 pallet template 取决于低级库的版本 2.0.0-alpha.8 。因此它可以在同样依赖于 2.0.0-alpha.8 的 runtime 中使用。

模块的开发依赖

Cargo.toml 文件的最后一部分指定了开发依赖项。这些依赖项是在模块的测试中需要用到的,而不是实际模块本身需要。

pallets/test-pallet/Cargo.toml

# --snip--

[dev-dependencies.sp-core]
git = 'https://github.com/paritytech/substrate.git'
default-features = false
tag = 'v2.0.0-alpha.8'

你可以通过以下命令来确认 Substrate pallet template 中的测试通过了:

cargo test

当更新模块来包含你自定义的逻辑时, 你可能需要向 Cargo.toml 文件添加自己的依赖项。

将模块添加到节点

当我们的模块以及编译并通过了测试,可以开始准备将其添加到我们的节点中。

如果你对包含和使用其他 crate 还不熟悉, 请参阅 the Cargo book[5] 以了解更多信息。

我们首先在节点的  runtime  Cargo.toml  中将新创建的 crate 添加为依赖项,然后告诉模块仅在 runtime 本身构建时,才构建其 std 功能,如下所示:

runtime/Cargo.toml

# --snip--

[dependencies.test-pallet]
default-features = false
path = '../pallets/test-pallet'

# toward the bottom
[features]
default = ['std']
std = [
'test-pallet/std',
# --snip--
]

你必须设置为 default_features = false 这样你的 runtime 才能成功编译为 Wasm。

接下来,我们通过将  test_pallet 添加到 construct_runtime! 宏中,来更新 runtime/src/lib.rs ,以实际使用我们新的 runtime pallet。

runtime/src/lib.rs

// add the following code block
impl test_pallet::Trait for Runtime {
  type Event = Event;
}

// --snip--
construct_runtime!(
  pub enum Runtime where
    Block = Block,
    NodeBlock = opaque::Block,
    UncheckedExtrinsic = UncheckedExtrinsic
  {
    // --snip--
    // add the following line
    TestPallet: test_pallet::{Module, Call, Storage, Event<T>},
  }
);

运行节点

至此,你已经将模块打包在自己的模块包中,并包含在节点的 runtime 中。


确保你返回了节点模板的根目录,然后使用以下命令编译并运行节点:

cargo build --release

清除所有现有的开发链 (在提示时输入 y ):

./target/release/node-template purge-chain --dev

启动节点:

./target/release/node-template --dev

最后,启动 Polkadot-JS Apps connecting to your local node[6] 确保模块按预期工作。

注意: 你还可以通过以下方式在 Polkadot-JS Apps 中手动设置节点 URL: 导航到设置标签, 并将要连接的远程节点/端点设置为本地节点

发布模块

一旦你的模块不再处于测试阶段,你应该考虑将其发布到 GitHub 或者 crates.io。

在 GitHub 上发布

要在 GitHub上发布, 你需要创建GitHub存储库[7]发布模块代码[8]

在 Crates.io 上发布

Crates.io 允许未经许可的发布。可以按照他们发布指南学习如何在Crate.io上发布[9]

更新 Runtime 依赖项

现在 Pallet 已经发布在 GitHub 或 crates.io,或者两个地方都发了,我们可以更新 runtime 以使用发布的代码,而不是硬编码的文件系统路径。

GitHub 的依赖项

runtime/Cargo.toml

[dependencies.your-pallet-name]
default_features = false
git = 'https://github.com/your-username/your-pallet'
branch = 'master'

# You may choose a specific commit or tag instead of branch
# rev = '<git-commit>'
# tag = '<some tag>

Crates.io 的依赖项

runtime/Cargo.toml

[dependencies.your-pallet-name]
default_features = false
version = 'some-compatible-version'

完善构建

再次编译,并且注意 Cargo 现在从 GitHub 或 crates.io 抓取你的 Pallet 而不是使用本地文件。

下一步

恭喜! 你已经成功编写并发布了一个 Substrate 模块在自己的 Rust 包中。其他的区块链开发者只需要在 Cargo.toml 文件中简单的使用 4 行代码并更新其 runtime 的 lib.rs 文件,就可以在他们的 runtime 中轻松使用你的 pallet。

了解更多

  • 我们还有 很多教程[10] 关于 Substrate 开发的概念和技术。
  • 更多信息关于 runtime 开发技巧和模式,请参阅 Substrate Recipes[11].

参考资料

  • The Cargo book[12]
  • 更多关于 Rust and WebAssembly[13] 的信息

参考链接

[1]

创建你的第一条Substrate链: https://www.substrate.io/tutorials/pallet-in-own-crate/tutorials/create-your-first-substrate-chain/v2.0.0-alpha.8

[2]

Substrate Node Template: https://github.com/substrate-developer-hub/substrate-node-template

[3]

Rust标准库: https://doc.rust-lang.org/std/

[4]

no_std: https://rust-embedded.github.io/book/intro/no-std.html

[5]

the Cargo book: https://doc.rust-lang.org/cargo/guide/creating-a-new-project.html

[6]

Polkadot-JS Apps connecting to your local node: https://polkadot.js.org/apps/#/explorer?rpc=ws://127.0.0.1:9944

[7]

创建GitHub存储库: https://help.github.com/en/articles/create-a-repo

[8]

发布模块代码: https://help.github.com/en/articles/pushing-to-a-remote

[9]

如何在Crate.io上发布: https://doc.rust-lang.org/cargo/reference/publishing.html

[10]

很多教程: https://www.substrate.io/tutorials

[11]

Substrate Recipes: https://substrate.dev/recipes/

[12]

The Cargo book: https://doc.rust-lang.org/stable/cargo/

[13]

Rust and WebAssembly: https://rustwasm.github.io/


原文:https://www.substrate.io/tutorials/pallet-in-own-crate/v2.0.0-alpha.8 

翻译:PolkaWorld 社区


  • 欢迎学习 Substrate: 

    https://substrate.dev/

  • 关注 Substrate 进展:

    https://github.com/paritytech/substrate

  • 关注 Polkadot 进展:

    https://github.com/paritytech/polkadot

  • 申请 Bootcamp: 

    https://bootcamp.web3.foundation/

更多内容:


Substrate:过去,现在和未来

在 Substrate 中为你的 runtime 添加合约模块

教程|创建你的第一条 Substrate 区块链


扫码关注公众号,回复 “1” 加入波卡群

关注 PolkaWorld

发现 Web 3.0 时代新机遇


点个 “在看” 再走吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存